package gu.sql2java.store;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

/**
 * 二进制数据本地存储实现
 * @author guyadong
 * @since 3.32.6
 *
 */
public abstract class BasesLocalBinaryStore extends BaseURLStore {
	static final String PROTOCOL = "lbs";
	private final URLStreamHandler handler = new Handler(); 
	/** 存储根路径 */
	protected File storeRoot;
	/**
	 * @param storeRoot 存储根路径
	 */
	public BasesLocalBinaryStore(File storeRoot) {
		this.storeRoot = storeRoot;
	}
	/**
	 * @param storeRoot 存储根路径
	 */
	public BasesLocalBinaryStore(String storeRoot) {
		this(new File(storeRoot));
	}

	@Override
	protected boolean doExists(URL storedURL){
		return pathOf(storedURL).canRead();
	}

	protected File pathOf(URL storedURL) {
		// 在path中添加root路径
		return new File(getStoreRoot().getPath(),storedURL.getPath());
	}
	
	@Override
	protected boolean doDelete(URL storedURL) throws IOException{
		File p = pathOf(storedURL);
		if(p.exists()){
			return p.delete();
		}
		return false;
	}

	@Override
	public final String getProtocol() {
		return PROTOCOL;
	}
	/**
	 * 返回存储URL对应的存储本地路径的URL
	 * @param storedUrl
	 */
	public URL asNativeUrl(URL storedUrl) {
		if(isStored(storedUrl)) {
			try {
				return pathOf(storedUrl).toURI().toURL();
			} catch (MalformedURLException e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}

	protected File getStoreRoot() {
		return ConditionChecks.checkNotNull(storeRoot, 
				IllegalStateException.class, 
				"storeRoot is uninitialized,please call setStoreRoot(File) firstly");
	}

	@Override
	protected URLStreamHandler doGetURLStreamHandler() {
		return handler;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + ((getProtocol() == null) ? 0 : getProtocol().hashCode());
		result = prime * result + ((storeRoot == null) ? 0 : storeRoot.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (!(obj instanceof BasesLocalBinaryStore))
			return false;
		BasesLocalBinaryStore other = (BasesLocalBinaryStore) obj;
		if (getProtocol() == null) {
			if (other.getProtocol() != null)
				return false;
		} else if (!getProtocol().equals(other.getProtocol()))
			return false;
		if (storeRoot == null) {
			if (other.storeRoot != null)
				return false;
		} else if (!storeRoot.equals(other.storeRoot))
			return false;
		return true;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("LocalBinaryStore [protocol=");
		builder.append(getProtocol());
		builder.append(",storeRoot=");
		builder.append(storeRoot);
		builder.append("]");
		return builder.toString();
	}

	private class Handler extends URLStreamHandler {
		@Override
		protected URLConnection openConnection(URL u) throws IOException {
			return new FileConnection(u);
		}
	}
	
	private class FileConnection extends URLConnection{

		protected FileConnection(URL url) {
			super(url);
		}

		@Override
		public void connect() throws IOException {
			connected = true;
		}

		@Override
		public InputStream getInputStream() throws IOException {
			connect();
			try {
				return new FileInputStream(pathOf(url));
			} catch (FileNotFoundException e) {
				throw new DataNotFoundException(url,e);
			}
		}
		
	}
}
